{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "from matplotlib.font_manager import FontProperties\n",
    "fonts = FontProperties(fname= \"\")\n",
    "import re\n",
    "import string\n",
    "import copy\n",
    "import time\n",
    "from sklearn.metrics import accuracy_score,confusion_matrix\n",
    "\n",
    "import torch\n",
    "from torch import nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "import torch.utils.data as Data\n",
    "import jieba\n",
    "from torchtext import data\n",
    "from torchtext.vocab import Vectors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [],
   "source": [
    "# import utils\n",
    "# datas = utils.load_thucnews()\n",
    "# THUCNews_data = pd.DataFrame(datas, columns=[\"words\", \"sentiment\"])\n",
    "# THUCNews_copy = THUCNews_data.copy()\n",
    "# index_THUCNews = THUCNews_copy['words'].count()\n",
    "# for i in range(int(index_THUCNews)):\n",
    "#         res = 0\n",
    "#         temp = THUCNews_copy['sentiment'][i]\n",
    "#         if temp == '体育':\n",
    "#             res = 1\n",
    "#         elif temp =='娱乐':\n",
    "#             res = 2\n",
    "#         elif temp =='家具':\n",
    "#             res = 3\n",
    "#         elif temp =='房产':\n",
    "#             res = 4\n",
    "#         elif temp =='教育':\n",
    "#             res = 5\n",
    "#         elif temp =='时尚':\n",
    "#             res = 6\n",
    "#         elif temp =='时政':\n",
    "#             res = 7\n",
    "#         elif temp =='游戏':\n",
    "#             res = 8\n",
    "#         elif temp =='科技':\n",
    "#             res = 8\n",
    "#         else:\n",
    "#             res = 10\n",
    "#         THUCNews_copy['sentiment'][i] = res\n",
    "#\n",
    "# THUCNews_copy['sentiment'] = THUCNews_copy['sentiment'].astype('int')\n",
    "#\n",
    "# train = THUCNews_copy.iloc[0:7500,:]\n",
    "# test = THUCNews_copy.iloc[7500:9000,:]\n",
    "# val = THUCNews_copy.iloc[9000:,:]\n",
    "# print(train)\n",
    "# print(test)\n",
    "# print(val)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [],
   "source": [
    "# train[[\"words\",\"sentiment\"]].to_csv(\"date/train.csv\",index = False)\n",
    "# test[[\"words\",\"sentiment\"]].to_csv(\"date/test.csv\",index = False)\n",
    "# val[[\"words\",\"sentiment\"]].to_csv(\"date/val.csv\",index = False)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [],
   "source": [
    "# train_data = pd.read_csv(\"date/train.csv\")\n",
    "# test_data = pd.read_csv(\"date/test.csv\")\n",
    "# val_data = pd.read_csv(\"date/val.csv\")"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [],
   "source": [
    "##  使用torchtext库进行数据准备\n",
    "# 定义文件中对文本和标签所要作的操作\n",
    "# sequential = True ## 表明输出的文本是字符而不是数值\n",
    "# tokenize = \"spacy\" ## 使用spacy切分词语\n",
    "# use_vocab = True  ## 创建一个词汇表\n",
    "# batch_first = True  ## batch优先的数据方式\n",
    "# fix_length = 400  ## 每个句子的固定长度为400\n",
    "## 定义文本切分方法，使用空格进行切分\n",
    "mytokenize = lambda x: x.split()\n",
    "TEXT = data.Field(sequential = True,tokenize = mytokenize,\n",
    "                  include_lengths=True, use_vocab=True,\n",
    "                  batch_first=True,fix_length=400)\n",
    "LABEL = data.Field(sequential = False,use_vocab=False,\n",
    "                  pad_token=None,unk_token=None)\n",
    "\n",
    "## 对所要读取的数据集的列进行处理\n",
    "text_data_fields = [\n",
    "    (\"words\" , TEXT),\n",
    "    (\"sentiment\" , LABEL)\n",
    "]\n",
    "## 读取数据\n",
    "traindata,valdata,testdata = data.TabularDataset.splits(\n",
    "    path=\"date/\" , format = \"csv\",\n",
    "    train = \"train_2.csv\",fields = text_data_fields,\n",
    "    validation = \"val_2.csv\",\n",
    "    test = \"test_2.csv\",skip_header=True\n",
    ")"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "data": {
      "text/plain": "(20910, 4590, 4500)"
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(traindata),len(valdata),len(testdata)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['瑞安', '航空', '或', '向', '中航', '商用', '订购', '架', '单通道', '飞机', '新浪', '财经', '讯', '北京', '时间', '月', '日', '晚间', '消息', '欧洲', '最大', '的', '廉价', '航空', '运营商', '瑞安', '航空公司', 'Ryanair', 'Holdings', '称', '该', '公司', '可能', '会', '向', '中航', '商用', '飞机', '有限公司', '以下', '简称', '中航', '商用', '订购', '至少', '架', '单通道', '喷气机', '在', '此', '以前', '瑞安', '航空', '已经', '与', '中航', '商用', '签署', '了', '一份', '协议', '将', '帮助', '后者', '开发', '机型', '瑞安', '航空', '对', '机型', '的', '一种', '变体', '感兴趣', '这种', '机型', '将', '可', '承载', '大约', '名', '乘客', '从', '年', '起', '开始', '发货', '瑞安', '航空', '首席', '执行官', '迈克尔', '奥里', '瑞', 'Michael', 'O', 'Leary', '在', '接受', '采访', '时称', '该', '公司', '到', '年', '将', '拥有', '架', '波音', 'BA', '飞机', '他', '表示', '如果', '经济', '状况', '的', '发展', '能', '让', '瑞安', '航空', '进入', '新', '的', '市场', '其', '需求量', '至少', '能', '满足', '当前', '机队', '的', '需求', '而且', '价格', '合适', '的话', '那么', '瑞安', '航空', '可能', '会', '组建', '一支', '混合', '机队', '中航', '商用', '计划', '在', '年', '对', '机型', '进行', '飞行', '测试', '到', '年', '投入使用', '这种', '飞机', '能', '承载', '大约', '名', '乘客', '其', '目标', '是', '打破', '空中客车', '和', '波音', '在', '单通道', '飞机', '市场', '上', '的', '双头', '垄断', '地位', '这一', '市场', '是', '民用', '航空业', '最大', '的', '组成部分', '瑞安', '航空', '称', '该', '公司', '还', '在', '与', '波音', '进行', '有关', '替换', '老', '飞机', '的', '谈判', '并', '表示', '该', '公司', '与', '中航', '商用', '之间', '达成', '的', '协议', '不会', '对', '其', '与', '波音', '的', '关系', '造成', '威胁', '奥里', '瑞', '还', '在', '巴黎', '召开', '新闻', '发布会', '表示', '该', '公司', '可能', '会', '使用', '其', '选择权', '来', '从', '波音', '订购', '架窄体', '飞机', '波音', '称', '对', '瑞安', '航空', '的', '意图', '作出', '评论', '是', '不合适', '的', '但', '同时', '表示', '瑞安', '航空', '是', '该', '公司', '极有', '价值', '的', '客户', '波音', '发言人', '迈克尔', '图尔', 'Michael', 'Tull', '称', '基于', '多年', '以来', '密切', '而', '成功', '的', '合作伙伴', '关系', '我们', '熟悉', '和', '了解', '瑞安', '航空', '的', '运营', '和', '机队', '要求', '文武', '欢迎', '发表', '评论', '我要', '评论']\n",
      "8\n"
     ]
    }
   ],
   "source": [
    "em = traindata.examples[0]\n",
    "print(em.words)\n",
    "print(em.sentiment)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [],
   "source": [
    "TEXT.build_vocab(traindata,max_size=20000,vectors = None)\n",
    "LABEL.build_vocab(traindata)\n",
    "# ## 可视化训练集中的前50个高频词\n",
    "# word_fre = TEXT.vocab.freqs.most_common(n=50)\n",
    "# word_fre = pd.DataFrame(data=word_fre,columns=[\"word\",\"fre\"])\n",
    "# word_fre.plot(x=\"word\",y=\"fre\",kind=\"bar\",legend=False,figsize=(12,7))\n",
    "# plt.xticks(rotation = 90,fontproperties = fonts,size = 10)\n",
    "# plt.show()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [],
   "source": [
    "## 定义一个迭代器，将类似长度示例一起批处理\n",
    "BATCH_SIZE = 64\n",
    "train_iter = data.BucketIterator(traindata,batch_size=BATCH_SIZE)\n",
    "val_iter = data.BucketIterator(valdata,batch_size=BATCH_SIZE)\n",
    "test_iter = data.BucketIterator(testdata,batch_size=BATCH_SIZE)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数据的类别标签：\n",
      " tensor([ 4,  1,  7,  1, 10,  3,  3,  5, 10, 10,  2,  7,  5,  8,  8,  5,  5,  1,\n",
      "         8,  5,  7,  8,  7,  7,  8,  3,  3,  6,  1,  3,  8,  5,  1,  7,  2,  1,\n",
      "         5,  7,  8,  5, 10,  3,  2,  8,  6,  6,  6, 10,  5,  1,  6,  4,  4,  6,\n",
      "         8, 10,  4,  3,  7,  3,  4, 10, 10,  7])\n",
      "数据的尺度： torch.Size([64, 400])\n",
      "数据样本数： 64\n"
     ]
    }
   ],
   "source": [
    "## 获取一个batch的数据，对数据进行内容的介绍\n",
    "for step,batch in enumerate(train_iter):\n",
    "    if step > 0:\n",
    "        break\n",
    "## 针对一个batch的数据，可以使用batch.sentiment获得数据的类别标签\n",
    "print(\"数据的类别标签：\\n\",batch.sentiment)\n",
    "print(\"数据的尺度：\",batch.words[0].shape)\n",
    "print(\"数据样本数：\",len(batch.words[1]))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [],
   "source": [
    "class LSTMNet(nn.Module):\n",
    "    def __init__(self,vocab_size,embedding_dim, hidden_dim ,layer_dim,output_dim):\n",
    "        super(LSTMNet,self).__init__()\n",
    "        self.hidden_dim = hidden_dim ## RNN神经元个数\n",
    "        self.layer_dim = layer_dim ## RNN层数\n",
    "        ## 对文本进行词向量处理\n",
    "        self.embedding = nn.Embedding(vocab_size,embedding_dim)\n",
    "        ## LSTM + 全连接层\n",
    "        self.lstm = nn.LSTM(embedding_dim,hidden_dim,layer_dim,batch_first=True)\n",
    "        self.fcl = nn.Linear(hidden_dim,output_dim)\n",
    "    def forward(self,x):\n",
    "        embeds = self.embedding(x)\n",
    "        r_out,(h_n,h_c) = self.lstm(embeds,None) # None 表示hidden state 会用全0的state\n",
    "        # 选取最后一个时间点的out输出\n",
    "        out = self.fcl(r_out[:,-1,:])\n",
    "        return out"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [
    {
     "data": {
      "text/plain": "LSTMNet(\n  (embedding): Embedding(20002, 100)\n  (lstm): LSTM(100, 128, batch_first=True)\n  (fcl): Linear(in_features=128, out_features=11, bias=True)\n)"
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "## 初始化网络\n",
    "vocab_size = len(TEXT.vocab)\n",
    "embedding_dim = 100\n",
    "hidden_dim = 128\n",
    "layer_dim = 1\n",
    "output_dim = 11\n",
    "lstm_model = LSTMNet(vocab_size,embedding_dim,hidden_dim,layer_dim,output_dim)\n",
    "lstm_model"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "outputs": [],
   "source": [
    "## 定义网络的训练过程函数\n",
    "## model 网络模型;  traindataloader 训练数据集;  valdataloader 验证数据集;\n",
    "## criterion 损失函数;  optimizer 优化方法; num_epochs 训练轮数\n",
    "def train_model2(model,traindataloader,valdataloader,criterion,\n",
    "                 optimizer,num_epochs=25):\n",
    "    train_loss_all = []\n",
    "    train_acc_all = []\n",
    "    val_loss_all = []\n",
    "    val_acc_all = []\n",
    "    since = time.time()\n",
    "    for epoch in range(num_epochs):\n",
    "        print(\"-\"* 10)\n",
    "        print(\"Epoch {}/{}\".format(epoch,num_epochs-1))\n",
    "        ## 每个epoch有两个阶段，训练阶段和验证阶段\n",
    "        train_loss = 0.0\n",
    "        train_corrects = 0\n",
    "        train_num = 0\n",
    "        val_loss = 0.0\n",
    "        val_corrects = 0\n",
    "        val_num = 0\n",
    "        model.train() ## 设置模型为训练模式\n",
    "        for step,batch in enumerate(traindataloader):\n",
    "            textdata,target = batch.words[0],batch.sentiment.view(-1)\n",
    "            out = model(textdata)\n",
    "            pre_lab = torch.argmax(out,1) ## 预测的标签\n",
    "            loss = torch.nn.functional.cross_entropy(out,target)  ## 计算损失函数\n",
    "            optimizer.zero_grad()\n",
    "            loss.backward()\n",
    "            optimizer.step()\n",
    "            train_loss += loss.item() * len(target)\n",
    "            train_corrects += torch.sum(pre_lab == target.data)\n",
    "            train_num += len(target)\n",
    "        ##  计算一个epoch在训练集上的损失和精度\n",
    "        train_loss_all.append(train_loss / train_num)\n",
    "        train_acc_all.append(train_corrects.double().item() / train_num)\n",
    "        print('{} Train Loss : {:.4f} Train Acc: {:.4f}'.format(\n",
    "            epoch,train_loss_all[-1],train_acc_all[-1]))\n",
    "\n",
    "        ## 计算一个epoch的训练后在验证集上的损失和精度\n",
    "        model.eval() ## 设置模型为训练模式评估模式\n",
    "        for step,batch in enumerate(valdataloader):\n",
    "            textdata,target = batch.words[0],batch.sentiment.view(-1)\n",
    "            out = model(textdata)\n",
    "            pre_lab = torch.argmax(out,1)\n",
    "            loss = torch.nn.functional.cross_entropy(out,target)\n",
    "            val_loss += loss.item() * len(target)\n",
    "            val_corrects += torch.sum(pre_lab == target.data)\n",
    "            val_num += len(target)\n",
    "        ## 计算一个epoch在训练集上的损失和精度\n",
    "        val_loss_all.append(val_loss / val_num)\n",
    "        val_acc_all.append(val_corrects.double().item() / val_num)\n",
    "        print('{} Val Loss : {:.4f} Val Acc: {:.4f}'.format(\n",
    "            epoch,val_loss_all[-1],val_acc_all[-1]))\n",
    "    train_process = pd.DataFrame(\n",
    "        data = {\"epoch\" : range(num_epochs),\n",
    "                \"train_loss_all\":train_loss_all,\n",
    "                \"train_acc_all\":train_acc_all,\n",
    "                \"val_loss_all\":val_loss_all,\n",
    "                \"val_acc_all\":val_acc_all})\n",
    "    return model,train_process"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "Epoch 0/9\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mKeyboardInterrupt\u001B[0m                         Traceback (most recent call last)",
      "\u001B[1;32m~\\AppData\\Local\\Temp/ipykernel_4396/4267347240.py\u001B[0m in \u001B[0;36m<module>\u001B[1;34m\u001B[0m\n\u001B[0;32m      3\u001B[0m \u001B[0mloss_func\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mnn\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mCrossEntropyLoss\u001B[0m \u001B[1;31m## 损失函数\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m      4\u001B[0m \u001B[1;31m## 对模型进行迭代训练，对所有数据训练Epoch轮\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m----> 5\u001B[1;33m lstm_model,train_process = train_model2(\n\u001B[0m\u001B[0;32m      6\u001B[0m     \u001B[0mlstm_model\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0mtrain_iter\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0mval_iter\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0mloss_func\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0moptimizer\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0mnum_epochs\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;36m10\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m      7\u001B[0m )\n",
      "\u001B[1;32m~\\AppData\\Local\\Temp/ipykernel_4396/3840795750.py\u001B[0m in \u001B[0;36mtrain_model2\u001B[1;34m(model, traindataloader, valdataloader, criterion, optimizer, num_epochs)\u001B[0m\n\u001B[0;32m     26\u001B[0m             \u001B[0mloss\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mtorch\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mnn\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfunctional\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mcross_entropy\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mout\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0mtarget\u001B[0m\u001B[1;33m)\u001B[0m  \u001B[1;31m## 计算损失函数\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m     27\u001B[0m             \u001B[0moptimizer\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mzero_grad\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 28\u001B[1;33m             \u001B[0mloss\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mbackward\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m     29\u001B[0m             \u001B[0moptimizer\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mstep\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m     30\u001B[0m             \u001B[0mtrain_loss\u001B[0m \u001B[1;33m+=\u001B[0m \u001B[0mloss\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mitem\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m*\u001B[0m \u001B[0mlen\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mtarget\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;32m~\\AppData\\Roaming\\Python\\Python38\\site-packages\\torch\\_tensor.py\u001B[0m in \u001B[0;36mbackward\u001B[1;34m(self, gradient, retain_graph, create_graph, inputs)\u001B[0m\n\u001B[0;32m    361\u001B[0m                 \u001B[0mcreate_graph\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mcreate_graph\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    362\u001B[0m                 inputs=inputs)\n\u001B[1;32m--> 363\u001B[1;33m         \u001B[0mtorch\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mautograd\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mbackward\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mgradient\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mretain_graph\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mcreate_graph\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0minputs\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0minputs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m    364\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    365\u001B[0m     \u001B[1;32mdef\u001B[0m \u001B[0mregister_hook\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mhook\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;32m~\\AppData\\Roaming\\Python\\Python38\\site-packages\\torch\\autograd\\__init__.py\u001B[0m in \u001B[0;36mbackward\u001B[1;34m(tensors, grad_tensors, retain_graph, create_graph, grad_variables, inputs)\u001B[0m\n\u001B[0;32m    171\u001B[0m     \u001B[1;31m# some Python versions print out the first line of a multi-line function\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    172\u001B[0m     \u001B[1;31m# calls in the traceback and some print out the last line\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 173\u001B[1;33m     Variable._execution_engine.run_backward(  # Calls into the C++ engine to run the backward pass\n\u001B[0m\u001B[0;32m    174\u001B[0m         \u001B[0mtensors\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mgrad_tensors_\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mretain_graph\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mcreate_graph\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0minputs\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m    175\u001B[0m         allow_unreachable=True, accumulate_grad=True)  # Calls into the C++ engine to run the backward pass\n",
      "\u001B[1;31mKeyboardInterrupt\u001B[0m: "
     ]
    }
   ],
   "source": [
    "## 定义优化器\n",
    "optimizer = torch.optim.Adam(lstm_model.parameters(),lr = 0.0003)\n",
    "loss_func = nn.CrossEntropyLoss ## 损失函数\n",
    "## 对模型进行迭代训练，对所有数据训练Epoch轮\n",
    "lstm_model,train_process = train_model2(\n",
    "    lstm_model,train_iter,val_iter,loss_func,optimizer,num_epochs=10\n",
    ")"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'train_process' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mNameError\u001B[0m                                 Traceback (most recent call last)",
      "\u001B[1;32m~\\AppData\\Local\\Temp/ipykernel_4396/2503897496.py\u001B[0m in \u001B[0;36m<module>\u001B[1;34m\u001B[0m\n\u001B[0;32m      5\u001B[0m \u001B[0mlstm_model\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m      6\u001B[0m \u001B[1;31m## 保存训练过程\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m----> 7\u001B[1;33m \u001B[0mtrain_process\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mto_csv\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;34m\"date/eng_lstm_model_process.csv\"\u001B[0m\u001B[1;33m,\u001B[0m\u001B[0mindex\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;32mFalse\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m      8\u001B[0m \u001B[0mtrain_process\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;31mNameError\u001B[0m: name 'train_process' is not defined"
     ]
    }
   ],
   "source": [
    "## 输出结果保存和数据保存\n",
    "torch.save(lstm_model,\"date/eng_lstm_model.pkl\")\n",
    "## 导入保存的模型\n",
    "lstm_model = torch.load(\"date/eng_lstm_model.pkl\")\n",
    "lstm_model\n",
    "## 保存训练过程\n",
    "train_process.to_csv(\"date/eng_lstm_model_process.csv\",index=False)\n",
    "train_process"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'train_process' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mNameError\u001B[0m                                 Traceback (most recent call last)",
      "\u001B[1;32m~\\AppData\\Local\\Temp/ipykernel_4396/366920677.py\u001B[0m in \u001B[0;36m<module>\u001B[1;34m\u001B[0m\n\u001B[0;32m      2\u001B[0m \u001B[0mplt\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfigure\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mfigsize\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;36m18\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;36m6\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m      3\u001B[0m \u001B[0mplt\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0msubplot\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;36m2\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m----> 4\u001B[1;33m plt.plot(train_process.epoch,train_process.train_loss_all,\n\u001B[0m\u001B[0;32m      5\u001B[0m          \"r.-\",label = \"Train loss\")\n\u001B[0;32m      6\u001B[0m plt.plot(train_process.epoch,train_process.val_loss_all,\n",
      "\u001B[1;31mNameError\u001B[0m: name 'train_process' is not defined"
     ]
    },
    {
     "data": {
      "text/plain": "<Figure size 1296x432 with 1 Axes>",
      "image/png": "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\n"
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "## 可视化模型过程\n",
    "plt.figure(figsize=(18,6))\n",
    "plt.subplot(1,2,1)\n",
    "plt.plot(train_process.epoch,train_process.train_loss_all,\n",
    "         \"r.-\",label = \"Train loss\")\n",
    "plt.plot(train_process.epoch,train_process.val_loss_all,\n",
    "         \"bs-\",label = \"Val loss\")\n",
    "plt.legend()\n",
    "plt.xlabel(\"Epoth number\",size = 13)\n",
    "plt.ylabel(\"Loss value\",size = 13)\n",
    "plt.subplot(1,2,2)\n",
    "plt.plot(train_process.epoch,train_process.train_acc_all,\n",
    "         \"r.-\",label = \"Train acc\")\n",
    "plt.plot(train_process.epoch,train_process.val_acc_all,\n",
    "         \"bs-\",label = \"Val acc\")\n",
    "plt.xlabel(\"Epoth number\",size = 13)\n",
    "plt.ylabel(\"Acc\",size = 13)\n",
    "plt.legend()\n",
    "plt.show()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "在测试集上的精度为： 0.906\n"
     ]
    }
   ],
   "source": [
    "## 对测试集进行预测并计算精度\n",
    "lstm_model = torch.load(\"date/lstm_model_2.pkl\")\n",
    "lstm_model.eval() ## 设置模型为训练模式评估模式\n",
    "test_y_all = torch.LongTensor()\n",
    "pre_lab_all = torch.LongTensor()\n",
    "for step,batch in enumerate(test_iter):\n",
    "    textdata,target = batch.words[0],batch.sentiment.view(-1)\n",
    "    out = lstm_model(textdata)\n",
    "    pre_lab = torch.argmax(out,1)\n",
    "    test_y_all = torch.cat((test_y_all,target)) ## 测试集标签\n",
    "    pre_lab_all = torch.cat((pre_lab_all,pre_lab)) ## 测试集的预测标签\n",
    "\n",
    "acc = accuracy_score(test_y_all,pre_lab_all)\n",
    "print(\"在测试集上的精度为：\",acc)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}